package xs.szw.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import xs.szw.common.constant.SystemConstant;
import xs.szw.service.model.vo.RouteVO;
import xs.szw.service.enums.MenuTypeEnum;
import xs.szw.service.enums.StatusEnum;
import xs.szw.service.model.pojo.sys.Menu;
import xs.szw.service.service.MenuService;
import xs.szw.service.mapper.MenuMapper;
import org.springframework.stereotype.Service;
import xs.szw.service.utils.SecurityUtils;

import java.util.*;

/**
* @author asus
* @description 针对表【sys_menu(菜单管理)】的数据库操作Service实现
* @createDate 2025-02-10 18:50:50
*/
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu>
    implements MenuService{

    /**
     * 获取当前用户菜单路由列表
     * @return
     */
    @Override
    public  List<RouteVO> getCurrentUserRoutes() {
        //1.获取当前用户角色集合
        Set<String> roles = SecurityUtils.getRoles();
        if(CollectionUtil.isEmpty(roles)){
            return Collections.emptyList();
        }
        //2.根据用户角色查询menu集合
        List<Menu> menuList;
        //判断是否是ROOT
        if(SecurityUtils.isRoot()){
            menuList = this.list(new LambdaQueryWrapper<Menu>().ne(Menu::getType, MenuTypeEnum.BUTTON.getValue()).orderByAsc(Menu::getSort));
        }else {
            menuList = this.baseMapper.getMenusByRoleCodes(roles);
        }
        //3.构建路由
        return buildRoutes(SystemConstant.ROOT_NODE_ID, menuList);
    }

    /**
     * 递归生成菜单路由层级列表
     * @param parentId
     * @param menuList
     * @return
     */
    private List<RouteVO> buildRoutes(Long parentId, List<Menu> menuList){

        List<RouteVO> routeList = new ArrayList<>();

        //循环递归遍历
        for (Menu menu : menuList){
           if(menu.getParentId().equals(parentId)){
               RouteVO routeVO = toRouteVo(menu);
               List<RouteVO> children = buildRoutes(menu.getId(), menuList);
               if(CollectionUtil.isNotEmpty(children)){
                   routeVO.setChildren(children);
               }
               routeList.add(routeVO);
           }

        };
        return routeList;
    }

    /**
     * 根据RouteBO创建RouteVO
     */
    private RouteVO toRouteVo(Menu menu) {
        RouteVO routeVO = new RouteVO();
        // 获取路由名称
        String routeName = menu.getRouteName();
        if(StrUtil.isBlank(routeName)){
            // 路由 name 需要驼峰，  capitalize -> 首字母大写  toCamelCase -> 将带有分隔符（如 - 或 _）的字符串转换为小驼峰命名格式
            routeName = StringUtils.capitalize(StrUtil.toCamelCase(menu.getRoutePath(), '-'));
        }
        // 根据name路由跳转 this.$router.push({name:xxx})
        routeVO.setName(routeName);

        // 根据path路由跳转 this.$router.push({path:xxx})
        routeVO.setPath(menu.getRoutePath());
        routeVO.setRedirect(menu.getRedirect());
        routeVO.setComponent(menu.getComponent());

        RouteVO.Meta meta = new RouteVO.Meta();
        meta.setTitle(menu.getName());
        meta.setIcon(menu.getIcon());
        meta.setHidden(StatusEnum.DISABLE.getValue().equals(menu.getVisible()));
        // 【菜单】是否开启页面缓存
        if (MenuTypeEnum.MENU.equals(menu.getType())
                && ObjectUtil.equals(menu.getKeepAlive(), 1)) {
            meta.setKeepAlive(true);
        }

        meta.setAlwaysShow(ObjectUtil.equals(menu.getAlwaysShow(), 1));
        String paramsJson = menu.getParams();
        // 将 JSON 字符串转换为 Map<String, String>
        if(StrUtil.isNotBlank(paramsJson)){
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                Map<String, String> paramMap = objectMapper.readValue(paramsJson, new TypeReference<>() {
                });
                meta.setParams(paramMap);
            }catch (Exception e) {
                throw new RuntimeException("解析参数失败", e);
            }
        }
        routeVO.setMeta(meta);
        return routeVO;
    }
}




